package com.xayy.health.mgt.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.kawins.base.result.CheckResult;
import cn.kawins.base.utils.BeanUtil;
import cn.kawins.base.utils.CollUtil;
import cn.kawins.base.utils.StringUtil;
import cn.kawins.mybatis.base.BaseServiceImpl;
import com.github.pagehelper.PageInfo;
import com.github.pagehelper.page.PageMethod;
import com.xayy.health.core.config.param.ModelFaultParams;
import com.xayy.health.core.enums.ModelTrainStatusEnum;
import com.xayy.health.mgt.mapper.ModelTrainRecordMapper;
import com.xayy.health.mgt.mapper.SatelliteNodeMapper;
import com.xayy.health.mgt.model.*;
import com.xayy.health.mgt.model.dto.ModelDto;
import com.xayy.health.mgt.model.vo.ModelInfoVo;
import com.xayy.health.mgt.service.ModelAlgorithmInfoService;
import com.xayy.health.mgt.service.ModelTrainAccuracyService;
import com.xayy.health.mgt.service.ModelTrainRecordService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import tk.mybatis.mapper.entity.Example;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author zhangxa
 */
@Service
public class ModelTrainRecordServiceImpl extends BaseServiceImpl<ModelTrainRecord> implements ModelTrainRecordService {

    @Autowired
    private ModelTrainRecordMapper modelTrainRecordMapper;
    @Autowired
    private ModelTrainAccuracyService modelTrainAccuracyService;
    @Autowired
    private ModelAlgorithmInfoService modelAlgorithmInfoService;
    @Autowired
    private ModelTrainRecordService modelTrainRecordService;

    @Autowired
    private SatelliteNodeMapper satelliteNodeMapper;

    /**
     * 模型训练集合信息列表分页
     *
     * @param modelDto 入参信息
     * @return 分页结果
     */
    @Override
    public PageInfo<ModelTrainRecord> pageList(ModelDto modelDto) {
        PageMethod.startPage(modelDto.getPage(), modelDto.getSize());
        List<ModelTrainRecord> modelTrainRecords = null;
        if (modelDto.getIsOldModel()) {
            modelTrainRecords = modelTrainRecordMapper.getListByStatus(modelDto);
        } else {
            modelTrainRecords = modelTrainRecordMapper.getList(modelDto);
        }
        if (!CollectionUtils.isEmpty(modelTrainRecords)) {
            ModelTrainRecord modelTrainRecord = modelTrainRecords.get(0);
            String liteCode = modelTrainRecord.getSatelliteCode();
            String satelliteNewId = satelliteNodeMapper.getSatelliteCode(liteCode);
            if (null != satelliteNewId) {
                for (ModelTrainRecord record : modelTrainRecords) {
                    record.setSatelliteCode(satelliteNewId);
                }
            }
        }
        return new PageInfo<>(modelTrainRecords);
    }

    /**
     * 事后诊断模型训练分割故障时间段
     *
     * @param modelTrain 入参信息
     */
    @Override
    public void handlingTimeToFailure(ModelTrain modelTrain) {
        long startTime = modelTrain.getStartTime().getTime();
        long endTime = modelTrain.getEndTime().getTime();
        List<ModelFaultParams> modelFaultParamsList = modelTrain.getDates();
        ArrayList<String> timeList = new ArrayList<>();
        ModelFaultParams faultParams = new ModelFaultParams();

        if (modelFaultParamsList.size() > 0) {
            if (modelFaultParamsList.get(0).getErrorStart().getTime() >= startTime) {
                faultParams.setErrorStart(new Date(startTime));
                faultParams.setErrorEnd(modelFaultParamsList.get(0).getErrorStart());
                timeList.add(faultParams.toString());
            }

            if (modelFaultParamsList.get(modelFaultParamsList.size() - 1).getErrorEnd().getTime() <= endTime) {
                faultParams.setErrorStart(modelFaultParamsList.get(modelFaultParamsList.size() - 1).getErrorEnd());
                faultParams.setErrorEnd(new Date(endTime));
                timeList.add(faultParams.toString());
            }
            for (int i = 0; i < modelFaultParamsList.size(); i++) {
                if (modelFaultParamsList.get(i).getErrorStart().getTime() >= startTime
                        && modelFaultParamsList.get(modelFaultParamsList.size() - 1).getErrorEnd().getTime() <= endTime) {
                    if (i < modelFaultParamsList.size() - 1) {
                        faultParams.setErrorStart(modelFaultParamsList.get(i).getErrorEnd());
                        faultParams.setErrorEnd(modelFaultParamsList.get(i + 1).getErrorStart());
                        timeList.add(faultParams.toString());
                    }
                }
            }
        }
        modelTrain.setTimeList(timeList);
    }

    /**
     * 校验模型名称是否重复
     *
     * @param modelTrain 入参信息
     * @return 结果日志
     */
    @Override
    public CheckResult<Object> checkModelName(ModelTrain modelTrain) {
        Example example = new Example(ModelTrainRecord.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("satelliteCode", modelTrain.getSatelliteCode());
        criteria.andEqualTo("paramCode", modelTrain.getParamCode());
        criteria.andEqualTo("modelType", modelTrain.getModelType());
        criteria.andEqualTo("modelName", modelTrain.getModelName());
        List<ModelTrainRecord> modelTrainRecords = selectByExample(example);
        if (CollUtil.isNotEmpty(modelTrainRecords)) {
            return CheckResult.fail("模型名称：" + modelTrain.getModelName() + "已存在！");
        }
        return CheckResult.success();
    }

    /**
     * 校验模型名称是否重复
     *
     * @param modelTrain 入参信息
     * @return 结果日志
     */
    @Override
    public CheckResult<Object> checkModelName(CalculateModelTrain modelTrain) {
        Example example = new Example(ModelTrainRecord.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("satelliteCode", modelTrain.getSatelliteCode());
        criteria.andEqualTo("paramCode", modelTrain.getParamCode());
        criteria.andEqualTo("modelType", modelTrain.getModelType());
        criteria.andEqualTo("modelName", modelTrain.getModelName());
        List<ModelTrainRecord> modelTrainRecords = selectByExample(example);
        if (CollUtil.isNotEmpty(modelTrainRecords)) {
            return CheckResult.fail("模型名称：" + modelTrain.getModelName() + "已存在！");
        }
        return CheckResult.success();
    }

    /**
     * 获取模型准确度
     *
     * @param modelTrainRecord 模型训练记录
     * @return ResultBody
     */
    @Override
    public CheckResult<Object> selectInfo(ModelTrainRecord modelTrainRecord) {
        ModelInfoVo modelInfoVo = new ModelInfoVo();
        String modelId = modelTrainRecord.getId();
        ModelTrainRecord info = selectById(modelId);
        List<ModelTrainAccuracy> result = modelTrainAccuracyService.selectList(modelId);
//        if(!CollectionUtils.isEmpty(result)){
//            result=addDataToList(result);
//
//        }
        modelInfoVo.setTestModel(result);

        List<ModelAlgorithmInfo> select =
                modelAlgorithmInfoService.select(ModelAlgorithmInfo.builder().modelId(modelId).build());

        List<AlgorithmParams> algorithmParamList = new ArrayList<>();
        if (CollUtil.isNotEmpty(select)) {
            select.forEach(x -> algorithmParamList.add(BeanUtil.copyBean(x, AlgorithmParams.class)));
        }

        if (info.getModelType() == 1) {
            // cnn
            CalculateModelTrain calculateModelTrain = BeanUtil.copyBean(info, CalculateModelTrain.class);
            calculateModelTrain.setAlgorithmParamList(algorithmParamList);
            modelInfoVo.setCalculateModelTrain(calculateModelTrain);
            calculateModelTrain.setModelName(info.getId());
        } else {
            // lstm
            ModelTrain modelTrain = BeanUtil.copyBean(info, ModelTrain.class);
            modelTrain.setAlgorithmParamList(algorithmParamList);
            modelTrain.setModelName(modelTrainRecord.getId());
            List<ModelFaultParams> dates = new ArrayList<>();
            String errorStart = info.getErrorStart();
            String errorEnd = info.getErrorEnd();
            if (StringUtil.isNotBlank(errorStart) && StringUtil.isNotBlank(errorEnd)) {
                String[] splitS = errorStart.split(",");
                String[] splitE = errorEnd.split(",");
                if (splitS.length == splitE.length) {
                    for (int i = 0; i < splitS.length; i++) {
                        DateTime parseS = DateUtil.parse(splitS[i], "yyyy-MM-dd HH:mm:ss");
                        DateTime parseE = DateUtil.parse(splitE[i], "yyyy-MM-dd HH:mm:ss");
                        ModelFaultParams modelFaultParams = new ModelFaultParams();
                        modelFaultParams.setErrorStart(parseS);
                        modelFaultParams.setErrorEnd(parseE);
                        dates.add(modelFaultParams);
                    }
                }

            }
            modelTrain.setDates(dates);
            modelInfoVo.setModelTrain(modelTrain);
        }
        return CheckResult.success(modelInfoVo);
    }


    /**
     * 补充缺失数据
     * @param taskTrendDataList 待补充集合
     * @return 补充完的集合
     */
//    private List<ModelTrainAccuracy> addDataToList(List<ModelTrainAccuracy> taskTrendDataList) {
//        List<ModelTrainAccuracy> resList=new ArrayList<>();
//        if (CollUtil.isNotEmpty(taskTrendDataList)) {
//            if(taskTrendDataList.size()>1){
//                for(int i=0;i<taskTrendDataList.size()-1;i++){
//                    ModelTrainAccuracy dto=taskTrendDataList.get(i);
//                    ModelTrainAccuracy dto2=taskTrendDataList.get(i+1);
//                    String time1 = dto.getTime();
//                    String time2 = dto2.getTime();
//                    time1= ConvertUtils.formatTime(time1);
//                    time2=ConvertUtils.formatTime(time2);
//                    DateTimeFormatter formatter= DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
//                    LocalDateTime timeFormatter1 = LocalDateTime.parse(time1, formatter);
//                    LocalDateTime timeFormatter2 = LocalDateTime.parse(time2, formatter);
//                    LocalDateTime timeFormatter3=timeFormatter1.plus(DiagnoseServiceImpl.AMOUNT_TO_ADD, ChronoUnit.MILLIS);
//                    dto.setTime(time1);
//                    resList.add(dto);
//                    if(timeFormatter2.isAfter(timeFormatter3)){
//                        String startLocalDate = timeFormatter3.toLocalDate() + " " + timeFormatter3.toLocalTime();
//                        if(16==startLocalDate.length()){
//                            startLocalDate=startLocalDate+":00";
//                        }
//                        if(!startLocalDate.contains(".")){
//                            startLocalDate=startLocalDate+".000";
//                        }
//                        ModelTrainAccuracy res=new ModelTrainAccuracy();
//                        res.setTime(startLocalDate);
//                        resList.add(res);
//                    }
//                }
//                ModelTrainAccuracy taskResultVo = taskTrendDataList.get(taskTrendDataList.size() - 1);
//                taskResultVo.setTime(ConvertUtils.formatTime(taskResultVo.getTime()));
//                resList.add(taskResultVo);
//            }else {
//                ModelTrainAccuracy taskResultVo = taskTrendDataList.get(0);
//                taskResultVo.setTime(ConvertUtils.formatTime(taskResultVo.getTime()));
//                resList.add(taskResultVo);
//            }
//
//        }
//        return resList;
//    }

    /**
     * 删除模型任务
     *
     * @param modelTypeId 模型任务id
     * @return ResultBody
     */
    @Override
    public CheckResult<Object> deleteModelTaskById(Long modelTypeId) {
        ModelTrainRecord modelTrainRecord = modelTrainRecordMapper.selectOne(ModelTrainRecord.builder().id(modelTypeId.toString()).build());
        modelTrainRecordMapper.deleteByPrimaryKey(modelTypeId);
        Example example = new Example(ModelTrainAccuracy.class);
        example.createCriteria().andEqualTo("modelTrainRecordId", modelTypeId);
        modelTrainAccuracyService.deleteByExample(example);
        return CheckResult.success("模型" + modelTrainRecord.getModelName() + "删除成功");
    }

    /**
     * 模型下拉列表
     * @param modelDto 入参
     * @return ResultBody
     */
    @Override
    public CheckResult<Object> getModel(ModelDto modelDto) {
        List<ModelTrainRecord> list = CollUtil.newArrayList();
        List<ModelTrainRecord> modelTrainRecords = null;
        ModelTrainRecord modelTrainRecord = ModelTrainRecord.builder().modelType(modelDto.getModelType()).satelliteCode(modelDto.getSatelliteCode()).status(ModelTrainStatusEnum.DONE.getCode()).build();
        ModelTrainRecord modelTrainRecordAndParamCode = ModelTrainRecord.builder().modelType(modelDto.getModelType()).satelliteCode(modelDto.getSatelliteCode()).paramCode(modelDto.getParamCode()).status(ModelTrainStatusEnum.DONE.getCode()).build();
        //isCurrentParams 0 匹配 1不匹配
        if (modelDto.getIsCurrentParams() == 1) {
            modelTrainRecords = modelTrainRecordService.select(modelTrainRecordAndParamCode);
        } else {
            modelTrainRecords = modelTrainRecordService.select(modelTrainRecord);
        }
        list.addAll(modelTrainRecords);
        return CheckResult.success(list);
    }
}
